package me.zhengjie.ppService;

import cn.hutool.core.util.ObjectUtil;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.pojo.ErrorInventoryReport;
import me.zhengjie.pojo.PPWarningResp;
import me.zhengjie.pojo.Resp;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class SseService {

    private static final Map<String, SseEmitter> sseEmitterMap = new ConcurrentHashMap<>();
    private final Thread worker = new Thread(task(), "定时推送");
    private final Gson gson = new GsonBuilder().serializeSpecialFloatingPointValues().create();
    private final PPInventoryService inventoryService;

    public SseService(PPInventoryService inventoryService){
        this.inventoryService = inventoryService;
        this.worker.setDaemon(true);
        this.worker.start();
    }

    public SseEmitter connect(String clientId) {
        SseEmitter sseEmitter = new SseEmitter(3600_000L);

        sseEmitter.onCompletion(() -> {
            log.info("结束连接：{}", clientId);
            sseEmitterMap.remove(clientId);
        });

        sseEmitter.onError(throwable -> {
            log.info("连接异常：{}", clientId);
            sseEmitterMap.remove(clientId);
        });

        sseEmitter.onTimeout(() -> {
            log.info("连接超时：{}", clientId);
            sseEmitterMap.remove(clientId);
        });

        sseEmitterMap.put(clientId, sseEmitter);
        log.info("创建新的sse连接，当前用户：{}", clientId);

        return sseEmitter;
    }

    private Runnable task(){
        return () -> {
            while (!this.worker.isInterrupted()) {
                try {
                    TimeUnit.SECONDS.sleep(5);
                } catch (Exception e) {
                    log.info("定时线程中断");
                    break;
                }
                try {
                    List<PPWarningResp> ppWarningResp = inventoryService.getPPWarningResp();
                    if(ObjectUtil.isEmpty(ppWarningResp)){
                        return;
                    }

                    ErrorInventoryReport report = new ErrorInventoryReport();
                    int expCount = 0;
                    int outTimeCount  = 0;

                    for (PPWarningResp resp : ppWarningResp) {
                        if ("outTime".equals(resp.getDateStatus())) {
                            outTimeCount++;
                        } else if ("exp".equals(resp.getDateStatus())) {
                            expCount++;
                        }
                    }
                    report.setExpQty(expCount);
                    report.setOutTimeQty(outTimeCount);

                    Resp resp = Resp.builder()
                            .msg("成功")
                            .status(200)
                            .data("inventory",report)
                            .build();

                    String json = this.gson.toJson(resp);
                    log.info("推送信息：{}", json);
                    broadcast(json);

                } catch (Exception e) {
                    Resp resp = Resp.builder()
                                    .msg("没有查询到物料信息")
                                    .status(500)
                                    .build();

                    String json = this.gson.toJson(resp);
                    log.info("推送信息：{}", json);
                    broadcast(json);
                }
            }
        };
    }

    private void broadcast(String json) {
        sseEmitterMap.forEach((k, v) -> {
            try {
                v.send(json, MediaType.APPLICATION_JSON);
            } catch (IOException e) {
                log.error("用户[{}]推送异常:{}", k, e.getMessage());
                sseEmitterMap.remove(k);
            }
        });
    }

}
